﻿
#include <iostream>
#include "../../win_com/xx_inline_hook.hpp"
#include "../../win_com/xx_mem.hpp"

//test_hook_jmp32
///////////////////////////////////////////////////////////

void hello_world()
{
	printf("[call %s]\n",__FUNCTION__);
}
void my_hello_world()
{
    printf("[call %s]\n", __FUNCTION__);
}


void test_hook_jmp32()
{
    // 修改被hook函数内存属性为可写
	xx_mem_unprotect(hello_world, 4096);
    // 在函数开头插入jmp语句，跳转到my_hello_world
	xx_setjmp32(&hello_world, &my_hello_world);
    // 测试一下
    hello_world();
}

//test_hook_jmp64
///////////////////////////////////////////////////////////
int __cdecl my_fclose(
    _Inout_ FILE* _Stream
) {
    printf("[call %s]\n", __FUNCTION__);
    return 0;
}

void test_hook_jmp64()
{
    // 判断偏移是否满足32位
    int64_t offset = xx_get_offset(&fclose, &my_fclose);
    bool need_far_jmp = xx_int32_overflow(offset);
    printf("need_far_jmp=%u \n", need_far_jmp);

    // 修改被hook函数内存属性为可写
    xx_mem_unprotect(&fclose, 1024);

    // 借助ret汇编指令实现64位跳转
    xx_setjmp64(&fclose, &my_fclose);
    // 测试一下
    fclose(nullptr);
}

//test_trampoline
///////////////////////////////////////////////////////////
char xx_trampoline[1024];
int sum(int a,int b)
{
    return a + b;
}
int mysum(int a, int b)
{
    printf("[call %s]!a=%d,b=%d\n", __FUNCTION__,a,b);

    //typedef int(sum_func_t)(int, int);
    //sum_func_t *f = (sum_func_t*)((char*)xx_trampoline);
    // 执行原逻辑
    auto ori_func = xx_trampoline_to_func(&sum, xx_trampoline);
    return (*ori_func)(a, b);;
}

void test_trampoline() 
{
    // 制作跳板
    xx_mem_unprotect(xx_trampoline,1024);
    xx_make_trampoline(&sum, xx_trampoline, 4+4);

    // hook
    xx_mem_unprotect(&sum, 1024);
    xx_setjmp(&sum, &mysum);

    // test
    int a = sum(1, 2);
    printf("a=%u\n",a);
}

//test_trampoline relocation
///////////////////////////////////////////////////////////
bool g_ready = true;
char xx_trampoline2[1024];

void flag_print() {
    if (g_ready) {
        printf("[call %s]!ready\n",__FUNCTION__);
    }
    else {
        printf("[call %s]!not ready\n", __FUNCTION__);
    }
}

void my_flag_print() {
    printf("[call %s]!\n", __FUNCTION__);
    auto ori = xx_trampoline_to_func(&flag_print, xx_trampoline2);
    (*ori)();
}
void test_trampoline_relocation() {
    // 制作跳板
    xx_mem_unprotect(xx_trampoline2, 1024);
    xx_make_trampoline(&flag_print, xx_trampoline2, 4 + 7);
    // 跳板偏移重定位
    xx_reloc_offset(&flag_print, xx_trampoline2, 4 + 3 );

    xx_setjmp(&flag_print, &my_flag_print);

    flag_print();
}

//test_trampoline  relocation offset too far
///////////////////////////////////////////////////////////
char *xx_trampoline3 = nullptr;

int WINAPI My_MessageBoxA(
    _In_opt_ HWND hWnd,
    _In_opt_ LPCSTR lpText,
    _In_opt_ LPCSTR lpCaption,
    _In_ UINT uType) 
{
    printf("[call %s]!\n", __FUNCTION__);

    auto ori = xx_trampoline_to_func(&MessageBoxA, xx_trampoline3);
    return (*ori)(hWnd, lpText, lpCaption, uType);
}

void test_trampoline_relocation_too_far()
{
    xx_trampoline3 = (char*)(&MessageBoxW);
    xx_mem_unprotect(xx_trampoline3, 1024);
    xx_make_trampoline(&MessageBoxA, xx_trampoline3, 4 + 3 +7 );
    xx_reloc_offset(&MessageBoxA, xx_trampoline3, 4 + 3 + 3);

    xx_mem_unprotect(&MessageBoxA, 1024);
    xx_setjmp(&MessageBoxA, &My_MessageBoxA);
    ::MessageBoxA(0, "text", "caption", 0);
}

int main()
{
    printf("\n\n======test_hook_jmp32=================\n");
	test_hook_jmp32();

    printf("\n\n======test_hook_jmp64=================\n");
    test_hook_jmp64();

    printf("\n\n======test_trampoline=================\n");
    test_trampoline();

    printf("\n\n======test_trampoline_relocation=================\n");
    test_trampoline_relocation();

    printf("\n\n======test_trampoline_relocation_too_far=================\n");
    test_trampoline_relocation_too_far();
	return 0;
}


